package com.music.service.system.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.code.kaptcha.Producer;
import com.music.dto.basic.UserDTO;
import com.music.dto.system.AccountDTO;
import com.music.dto.system.KaptchaDTO;
import com.music.dto.system.TokenDTO;
import com.music.dto.utils.OpResultDTO;
import com.music.dto.utils.ResultJsonObject;
import com.music.entity.basic.UserEntity;
import com.music.mapper.basic.UserMapper;
import com.music.service.basic.UserService;
import com.music.service.system.AccountService;
import com.music.utils.JWTUtil;
import com.music.utils.RedisUtil;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Date;

@Service
public class AccountServiceImpl implements AccountService {

    @Value(value = "${application.jwt.expire}")
    private Integer expire;
    @Resource
    private Producer kaptchaProducer;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private UserService userService;
    @Resource
    private UserMapper userMapper;

    @Override
    public Integer register(UserDTO userDTO) throws Exception {
        UserDTO user = userMapper.getByLoginName(userDTO.getLoginName());
        if (user == null) {
            MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
            UserEntity userEntity = mapperFactory.getMapperFacade().map(userDTO, UserEntity.class);
            userEntity.setGmtCreate(new Date());
            return userMapper.add(userEntity);
        }
        return -1; // -1则用户名已被占用
    }

    @Override
    public JSONObject loginCheck(String loginName, String loginPwd, String randomId, String authCode) throws Exception {
        JSONObject jsonObject = new ResultJsonObject();
        TokenDTO tokenDTO = new TokenDTO();
        OpResultDTO opResult = new OpResultDTO();
        AccountDTO accountDTO = new AccountDTO();
        if (randomId == null || redisUtil.get(randomId) == null) {
            opResult.setResult(JSONObject.parseObject("{ isLogin: false }"));
            jsonObject.put("data", opResult);
            jsonObject.put("message", "验证码已过期，请单击刷新");
            jsonObject.put("status", 401);
        } else if (!((String) redisUtil.get(randomId)).equalsIgnoreCase(authCode)) {
            opResult.setResult(JSONObject.parseObject("{ isLogin: false }"));
            jsonObject.put("data", opResult);
            jsonObject.put("message", "验证码错误");
            jsonObject.put("status", 401);
        } else {
            UserDTO userDto = userService.loginCheck(loginName);
            if (userDto == null || !userDto.getLoginPwd().equals(loginPwd)) {
                opResult.setResult(JSONObject.parseObject("{ isLogin: false }"));
                jsonObject.put("data", opResult);
                jsonObject.put("message", "用户名或密码错误");
                jsonObject.put("status", 401);
            } else {
                accountDTO.setId(userDto.getUserId());
                accountDTO.setName(userDto.getUserName());
                // 生成签名DTO，包含账号(用户)ID
                tokenDTO.setAccountId(userDto.getUserId());
                accountDTO.setToken(JWTUtil.createSign(tokenDTO.toString(), expire));
                opResult.setResult(accountDTO);
                jsonObject.put("data", opResult);
                jsonObject.put("message", "");
                jsonObject.put("status", 200);
            }
        }
        return jsonObject;
    }

    @Override
    public AccountDTO getInfo(String token) throws Exception {
        AccountDTO accountDTO = new AccountDTO();
        TokenDTO tokenDTO = JWTUtil.verifyToken(token);
        UserDTO userDto = userService.getByUserId(tokenDTO.getAccountId());
        accountDTO.setId(userDto.getUserId());
        accountDTO.setName(userDto.getUserName());
        accountDTO.setUsername(userDto.getLoginName());
        accountDTO.setAvatar(userDto.getImageUrl());
        accountDTO.setCreateTime(userDto.getGmtCreate());
        accountDTO.setToken(JWTUtil.createSign(tokenDTO.toString(), expire));
        return accountDTO;
    }

    @Override
    public KaptchaDTO getKaptcha() throws Exception {
        // 生成验证码
        String text = kaptchaProducer.createText();
        BufferedImage bufferedImage = kaptchaProducer.createImage(text);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(bufferedImage, "png", outputStream);
        BASE64Encoder base64Encoder = new BASE64Encoder();
        String base64 = base64Encoder.encode(outputStream.toByteArray());
        String captchaBase64 = "data:image/png;base64," + base64.replaceAll("\r\n", "");
        // 存入Redis数据库
        String randomId = RandomStringUtils.random(15, true, true);
        redisUtil.set(randomId, text, 60);
        // 生成验证码返回数据
        KaptchaDTO kaptchaDTO = new KaptchaDTO();
        kaptchaDTO.setUuid(randomId);
        kaptchaDTO.setImage(captchaBase64);
        kaptchaDTO.setExpire(60);
        return kaptchaDTO;
    }

    @Override
    public JSONObject quickLogin(JSONObject object) throws Exception {
        JSONObject result = new JSONObject();
        TokenDTO tokenDTO = new TokenDTO();
        OpResultDTO opResult = new OpResultDTO();
        AccountDTO accountDTO = new AccountDTO();

        String codeNumber = object.getString("codeNumber");
        String loginNumber = JWTUtil.getSeed(codeNumber);
        UserDTO userDTO = userService.loginCheck(loginNumber);
        if (userDTO == null) {
            opResult.setResult(JSONObject.parseObject("{ isLogin: false }"));
            result.put("data", opResult);
            result.put("message", "用户信息有误");
            result.put("status", 401);
        } else {
            accountDTO.setId(userDTO.getUserId());
            accountDTO.setName(userDTO.getUserName());
            // 生成签名DTO，包含账号(用户)ID
            tokenDTO.setAccountId(userDTO.getUserId());
            accountDTO.setToken(JWTUtil.createSign(tokenDTO.toString(), expire));
            opResult.setResult(accountDTO);
            result.put("data", opResult);
            result.put("message", "");
            result.put("status", 200);
        }
        return result;
    }
}
